import java.util.Arrays;

public class demo {


//    冒泡排序

    public static void bubbleSort(int[] arr){
//        i表示躺数
        for (int i = 0; i < arr.length-1; i++) {
             int flag = 1;
             for (int j = 0; j < arr.length-1-i; j++) {
                 if (arr[j] > arr[j+1]) {
                     int tmp = arr[j];
                     arr[j] = arr[j+1];
                     arr[j+1] = tmp;
                     flag = 0;
                 }
             }
             if (flag == 1) {
                 break;
             }
        }
    }
    public static void main(String[] args) {
        int[] arr1 = {2,5,3,7,1,9};
        int[] arr2 = {2,5,3,7,1,9};
        System.out.println(Arrays.toString(arr1));
        bubbleSort(arr1);
        System.out.println(Arrays.toString(arr1));
//        还有一种 Arrays.sort(arr1);方法 也是一样的 是这个工具类
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2));
    }










//    判断数组是否是有序
    public static boolean isUp(int[] arr){
        for (int i = 0; i < arr.length-1; i++) {
//            这里得写arr.length-1 不然下面的arr[i+1] 会发生数组越界
//            也不可以写arr[i] < arr[i - 1] 这样当数组i=0时 也会发生数组越界
            if (arr[i] > arr[i + 1]){
                return false;
            }
        }
        return true;
    }
    public static void main9(String[] args) {

        int[] arr1 = {11,22,33,44,55};
        System.out.println(isUp(arr1));
    }












//    二分查找 前提：数组一定得是有序的数组
//    在Arrays.binarySearch() 这个方法也是二分查找  System.out.println(Arrays.binarySearch(arr, 34));
    public static int binarySearch(int[] arr, int key){

        int left = 0;
        int right = arr.length-1;
        while(left < right){
            int mid = (left + right) / 2;
            if (arr[mid] > key){
                right = mid - 1;
            }
            else if (arr[mid] < key){
                left = mid +1;
            }
            else {
                return mid;
            }
        }
        return -1;
    }
//    查找数组中指定元素(顺序查找) 给定一个数组, 再给定一个元素, 找出该元素在数组中的位置.
    public static int findNum(int[] arr, int key){
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == key){
                return i;
            }
        }
        return -1;//这里-1 是因为数组的下标 不可能存在负数
    }
//    求数组的平均值
    public static double avg(int[] arr){
        int sum = 0;
        for (int x : arr) {
            sum += x;
        }
        return (double)sum / (double)arr.length;
//        这里可能会出现小数情况 所以最好强制类型转化成double return的返回值 最好也是double
//        这里如果arr = {} 输出结果为NaN
    }
    //    给定一个整型数组, 找到其中的最大元素 (找最小元素同理)
    public static int findMax(int[] arr){
        if (arr == null) return -1;//-1是相当于业务上的处理 后面学到异常在写 报异常代码
        if (arr.length == 0) return -1;
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (max < arr[i]){
                max = arr[i];
            }
        }
        return max;
    }
    public static int findMix(int[] arr){
        if (arr == null || arr.length == 0) return -1;

        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (min > arr[i]){
                min = arr[i];
            }
        }
        return min;
    }
    public static void main8(String[] args) {
        int[] arr = {23,12,34,2,45};
        System.out.println(findMax(arr));
        System.out.println(findMix(arr));
        System.out.println(avg(arr));
        System.out.println();
        System.out.println(findNum(arr,34));
        System.out.println(findNum(arr,100));
        System.out.println();
        int[] arr1 = {12,23,34,45,56};
        System.out.println(binarySearch(arr1, 34));
    }
//    这样代码还是有错误
//    1.因为我又没写 arr等于null情况时
//    所以加上判断条件  if (arr == null) return -1；
//    2.当arr = {}时 此时 arr的长度是0  你在方法中调用 arr[0] 会报错（数组越界）
//    所以加上判断条件 if (arr.length == 0) return -1;










//    实现一个toString()方法
    public static String myToString(int[] arr){
        if(arr == null) return "null";
        String str = "[";
        for (int i = 0; i < arr.length; i++) {
            str += arr[i];
            if (i != arr.length-1){
                str += ", ";
            }
        }
        str += "]";
        return str;
    }// [1, 2, 3, 4, 5]
    public static void main7(String[] args) {
        int[] arr = {};
        String str = myToString(arr);
        System.out.println(str);

        System.out.println(Arrays.toString(arr));
    }
//    这样的代码还是有问题
//    1.如果 给定的数组是null 那么在myToString方法中 就会报空值异常
//    所以加上判断条件 if(arr == null) return "null"；
//    2.如果 给定的数组int[] arr = {} 那么就会输出一个括号[]
//










//    写一个方法, 将数组中的每个元素都 * 2
    public static void func1(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * 2;
        }
    }
    public static int[] func2(int[] arr){//也可以数组作为方法的返回值
        int[] ret = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            ret[i] = arr[i] * 2;
        }
//        System.out.print(Arrays.toString(ret));
//        System.out.println();

        return ret;

    }
    public static void main6(String[] args) {
        int[] arr1 = {1,2,3,4,5};
        func1(arr1);
        System.out.println(Arrays.toString(arr1));
//        原来来的数组变了

        int[] arr2 = {12,23,34,45,56};
//        func2(arr2);
        int[] ret = func2(arr2);
        System.out.println(Arrays.toString(arr2));
        System.out.println(Arrays.toString(ret));
//        原来来的数组没变
    }












//  交换两个数
    public static void swap(int[] arr){
        int tmp = arr[0];
        arr[0] = arr[1];
        arr[1] = tmp;
    }
    public static void main5(String[] args) {
        int[] arr = {10,20};
        System.out.println("交换前："+ arr[0] + " " + arr[1]);
        swap(arr);
        System.out.println("交换后："+ arr[0] + " " + arr[1]);
    }









    public static void main4(String[] args) {
        int[] arr1 = {1,2,3,4,5,12};
        int[] arr2 = arr1;
//        代表：arr2这个引用指向arr1这个引用指向的对象
//        引用 指向 引用：这句话是错误的 引用只能指向对象

        int[] arr3 = null;
//        这个引用不指向任何对象


        int[] arr4 = new int[]{1,2,3,123,2};
        arr4 = new int[10];
        arr4 = new int[5];
        arr4 = new int[3];
        System.out.println(arr4.length);
//        一个引用 不可以同时指向同一个对象
//        一个引用只能保存 一个对象的地址

//        引用一定在 栈上吗  不一定  一个变量在不在栈上 是你变量的性决定的
//        如果你就是一个局部变量 那一定在栈上    如果是实例成员变量 那就不一定就是在栈上

    }










    public static void fun1(int[] arr){
        arr = new int[]{12,23,34,45,56};
    }
    public static void fun2(int[] arr){
        arr[0] = 123;
    }
    public static void main2(String[] args) {
        int[] arr1= {1,2,3,4,5,6};
        System.out.println("f1:");
        System.out.println(Arrays.toString(arr1));
        fun1(arr1 );
        System.out.println(Arrays.toString(arr1));
//      f1:
//      [1,2,3,4,5,6]
//      [1,2,3,4,5,6]
//      在引用传递的时候 fun1会在栈上再开辟一块空间 存放arr1的地址 当arr = new int[]{12,23,34,45,56};
//      会在堆上在开辟一块空间存放{12,23,34,45,56} 会使得fun1里面在栈上的arr指向{12,23,34,45,56}对象的地址
//      所以 实参并没有改变             所以  不一定 我传了地址 就一定会改变实参的值
//      虽然你传的是地址 但是传过去后 形参只是改变了自己的指向而已

        int[] arr2= {1,2,3,4,5,6};
        System.out.println("f2:");
        System.out.println(Arrays.toString(arr2));
        fun2(arr2);
        System.out.println(Arrays.toString(arr2));
//      f2:
//      [1,2,3,4,5,6]
//      [123,2,3,4,5,6]
//        在引用传递的时候 fun2会在栈上再开辟一块空间 存放arr1的地址 通过arr[0] = 123;找到对象
 //       {1,2,3,4,5,6}的0下标 然后更改
    }















    public static void print(int[] arr1){
        for (int i = 0; i < arr1.length; i++) {
            System.out.print(arr1[i] + " ");
        }
    }
    public static void main1(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        //arr是局部变量 在栈会占用一块内存  arr变量存储的是{1,2,3,4,5,6}对象首元素的地址
        //所以arr还被称为：引用变量 引用指向一个对象  引用存储的是变量的地址
        //{1,2,3,4,5,6}这些是对象 它们在堆上 会分配6块合适的内存
        //在java中java数组是一个对象 对象存放在堆里

        //在jvm中 有这些部分
        //java虚拟机栈（平常所说的栈）：局部变量
        //本地方法栈：C/C++代码
        //方法区：静态变量
        //堆：对象
        //程序计数器：类似于提醒你最后一次写代码写到哪

        int[] arr2 = null;
        //这个引用不指向任何对象
//        System.out.println(arr2.length);
//     .NullPointerException 会报错 空指针异常 使用索引也是一样


        print(arr);
        //通过arr按 （引用传递） 传给print函数 也可以叫做按值传递
        //print里面的arr1也会在栈上开辟一块空间 然后存放arr的地址指向arr的对象
    }


}
